package main

import (
	"fmt"
	"log"
	"time"

	"github.com/spf13/pflag"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	UserId   string     `gorm:"column:user_id"`
	Mobile   string     `gorm:"column:mobile"`
	Password string     `gorm:"column:password"`
	NickName string     `gorm:"column:nickname"`
	HeadUrl  string     `gorm:"column:head_url"`
	Birthday *time.Time `gorm:"column:birthday"`
	Address  string     `gorm:"column:address"`
	Describe string     `gorm:"column:describe"`
	Gender   string     `gorm:"column:gender"`
	Role     string     `gorm:"column:role"`
}

func (p *User) TableName() string {
	return "user"
}

var (
	host     = pflag.StringP("host", "H", "bj-cynosdbmysql-grp-h5c4g592.sql.tencentcdb.com:28461", "MySQL service host address")
	username = pflag.StringP("username", "u", "root", "Username for access to mysql service")
	password = pflag.StringP("password", "p", "Zhenzhong666", "Password for access to mysql, should be used pair with password")
	database = pflag.StringP("database", "d", "user", "Database name to use")
	help     = pflag.BoolP("help", "h", false, "Print this help message")
)

func main() {
	// Parse command line flags
	pflag.CommandLine.SortFlags = false
	pflag.Usage = func() {
		pflag.PrintDefaults()
	}
	pflag.Parse()
	if *help {
		pflag.Usage()
		return
	}

	dsn := fmt.Sprintf(`%s:%s@tcp(%s)/%s?charset=utf8&parseTime=%t&loc=%s`,
		*username,
		*password,
		*host,
		*database,
		true,
		"Local")
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// 1. Auto migration for given models
	//db.AutoMigrate(&User{})

	// 2. Insert the value into database
	if err := db.Create(&User{Mobile: "15510835135"}).Error; err != nil {
		log.Fatalf("Create error: %v", err)
	}
	PrintUsers(db)

	// 3. Find first record that match given conditions
	user := &User{}
	if err := db.Where("code= ?", "D42").First(&user).Error; err != nil {
		log.Fatalf("Get product error: %v", err)
	}

	// 4. Update value in database, if the value doesn't have primary key, will insert it
	user.Mobile = "1891050252"
	if err := db.Save(user).Error; err != nil {
		log.Fatalf("Update product error: %v", err)
	}
	PrintUsers(db)

	// 5. Delete value match given conditions
	if err := db.Where("code = ?", "D42").Delete(&User{}).Error; err != nil {
		log.Fatalf("Delete product error: %v", err)
	}
	PrintUsers(db)
}

// PrintUsers List products
func PrintUsers(db *gorm.DB) {
	users := make([]*User, 0)
	var count int64
	d := db.Where("code like ?", "%D%").Offset(0).Limit(2).Order("id desc").Find(&users).Offset(-1).Limit(-1).Count(&count)
	if d.Error != nil {
		log.Fatalf("List products error: %v", d.Error)
	}

	log.Printf("totalcount: %d", count)
	for _, user := range users {
		log.Printf("\tMobile: %s, ID: %d\n", user.Mobile, user.ID)
	}
}
